﻿#region License

// Copyright (c) 2011, Matt Holmes
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification, are permitted provided 
// that the following conditions are met:
// 
// * Redistributions of source code must retain the above copyright notice, this list of conditions and the 
//   following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
//   the following disclaimer in the documentation and/or other materials provided with the distribution.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
// OF THE POSSIBILITY OF SUCH DAMAGE.

#endregion

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Interop;

namespace SkyrimTweaker.Common.Controls {
	public class PopupEx : Popup {
		#region Fields

		public static readonly DependencyProperty TopmostProperty =
			DependencyProperty.Register ("Topmost", typeof (bool), typeof (PopupEx), new UIPropertyMetadata (false, OnTopmostChanged));

		#endregion

		#region Properties

		public bool Topmost {
			get { return (bool) GetValue (TopmostProperty); }
			set { SetValue (TopmostProperty, value); }
		}

		#endregion

		#region Protected Methods

		protected override void OnOpened (EventArgs e) {
			SetTopmostState (Topmost);
			base.OnOpened (e);
		}

		#endregion

		#region Private Methods

		private static void OnTopmostChanged (DependencyObject obj, DependencyPropertyChangedEventArgs e) {
			var popup = (PopupEx) obj;
			popup.SetTopmostState (popup.Topmost);
		}

		private void SetTopmostState (bool isTop) {
			if (Child == null)
				return;

			var hwndSource = (PresentationSource.FromVisual (Child)) as HwndSource;

			if (hwndSource == null) {
				return;
			}

			var hwnd = hwndSource.Handle;

			NativeInterop.RECT rect;

			if (!NativeInterop.GetWindowRect (hwnd, out rect)) {
				return;
			}

			Debug.WriteLine ("setting z-order " + isTop);

			if (isTop) {
				NativeInterop.SetWindowPos (hwnd, NativeInterop.HWND_TOPMOST, rect.Left, rect.Top, (int) Width, (int) Height, NativeInterop.TOPMOST_FLAGS);
			}
			else {
				// Z-Order would only get refreshed/reflected if clicking the
				// the titlebar (as opposed to other parts of the external
				// window) unless I first set the popup to HWND_BOTTOM
				// then HWND_TOP before HWND_NOTOPMOST
				NativeInterop.SetWindowPos (hwnd, NativeInterop.HWND_BOTTOM, rect.Left, rect.Top, (int) Width, (int) Height, NativeInterop.TOPMOST_FLAGS);
				NativeInterop.SetWindowPos (hwnd, NativeInterop.HWND_TOP, rect.Left, rect.Top, (int) Width, (int) Height, NativeInterop.TOPMOST_FLAGS);
				NativeInterop.SetWindowPos (hwnd, NativeInterop.HWND_NOTOPMOST, rect.Left, rect.Top, (int) Width, (int) Height, NativeInterop.TOPMOST_FLAGS);
			}
		}

		#endregion
	}
}
